﻿using Inaction.ServiceContract;
using Inaction.Core;
using Inaction.Mapping;
using Inaction.Resource.Properties;
using Inaction.Util;
using System;
using System.ComponentModel;
using System.Linq;

namespace Inaction.Business
{
    [Serializable]
    public partial class Entity<T> : Inaction.Entity<T>, IEntity
        where T : Entity<T>, new()
    {
        #region  IEntity
        Inaction.Core.IEntity master = null;
        [Browsable(false)]
        public override Inaction.Core.IEntity Master
        {
            get { return master; }
            set
            {
                master = value;
                if (master != null)
                {
                    var masterClassInfo = ClassInfo.LoadInfo(master.GetType());
                    var masterTable = masterClassInfo.Table;

                    IProperty foreignProperty = null;
                    var foreignKey = ClassInfo.Table.ForeignKeys.FirstOrDefault(p => p.ReferenceTable.Name.Equals(masterTable.Name, StringComparison.OrdinalIgnoreCase));
                    if (foreignKey == null)
                    {
                        foreignProperty = ClassInfo.GetMasterAddtionRelationship(master.GetType());
                        if (foreignProperty == null)
                        {
                            foreignProperty = masterClassInfo.GetChildAddtionRelationship(typeof(T));
                        }
                        if (foreignProperty == null)
                        {
                            throw new Exception(string.Format(Resources.NoForeignKeyRelationships,
                                masterTable.Name, ClassInfo.TableName));
                        }
                    }
                    else
                    {
                        foreignProperty = ClassInfo.ColumnProperties[foreignKey.Column.Name];
                    }
                    foreignProperty.SetFieldValue(this, Master.PrimaryKey);
                }
            }
        }

        [Browsable(false)]
        public IEntityList List { get; internal set; }
        public virtual bool CanSetProperty(string property)
        {
            return true;
        }
        public new void SetDefaultValue()
        {
            if (ClassInfo.CreaterProperty != null)
            {
                var val = Inaction.Security.Principal.Instance.Identity.UserNumber;
                ClassInfo.CreaterProperty.SetFieldValue((T)this, val);
            }
            if (ClassInfo.CreateTimeProperty != null)
            {
                var val = DateTime.Now;
                ClassInfo.CreateTimeProperty.SetFieldValue((T)this, DateTime.Now);
            }
            if (ClassInfo.UpdaterProperty != null)
            {
                var val = Inaction.Security.Principal.Instance.Identity.UserNumber;
                ClassInfo.UpdaterProperty.SetFieldValue((T)this, val);
            }
            if (ClassInfo.UpdateTimeProperty != null)
            {
                var val = DateTime.Now;
                ClassInfo.UpdateTimeProperty.SetFieldValue((T)this, val);
            }
            foreach (var p in ClassInfo.DefaultValueProperties)
            {
                var val = p.DefaultValue;
                p.SetFieldValue((T)this, p.DefaultValue);
            }
        }

        public bool CheckExistsForeignKeyChildrenData(ref string error, System.Data.IDbTransaction trans = null)
        {
            var classInfo = ClassInfo.LoadInfo(typeof(T));
            if (classInfo != null && classInfo.DeletedProperty == null)
            {
                var sqls = SqlStatement.GetForeignKeyChildrenStatement<T>((T)this);
                if (sqls == null) return false;
                if (trans == null)
                {
                    var con = DbProvider.Connection;
                    trans = con.BeginTransaction();
                }
                foreach (var s in sqls)
                {
                    using (var command = DbProvider.CreateCommand(trans, s))
                    {
                        var count = (int)command.ExecuteScalar();
                        if (count > 0)
                        {
                            error = string.Format(Inaction.Resource.Properties.Resources.ExistsForeignKeyChildrenData, classInfo.DisplayName, s.Name);
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        #endregion
    }
}